package com.mysterymall.Common.Config;

import com.mysterymall.Task.CoreJob;

import java.util.concurrent.*;

/**
 * 自定义线程池
 */
public class MyThreadPoolExecutor implements Executor {

    //创建线程的工厂对象
    private final ThreadFactory threadFactory;
    //临时工的空闲时间上限
    private final long keepAliveTime;
    private final TimeUnit unit;
    //当前正式员工的数量
    private int currentCoreSize;
    //最大正式员工的数量
    private final int corePoolSize;

    //当前临时工的数量
    private int currentTemporarySize;
    //临时员工的上限
    private int temporaryPoolSize;

    //传递任务的阻塞队列
    private final BlockingQueue<Runnable> workQueue;

    //构造方法

    /**
     * @param corePoolSize    正式员工的数量
     * @param maximumPoolSize 员工上限
     * @param keepAliveTime   临时工执行时间上限
     * @param unit            时间单位
     * @param workQueue       工作队列
     * @param threadFactory   线程工厂
     * @param handler         拒绝策略
     */
    public MyThreadPoolExecutor(
            int corePoolSize,
            int maximumPoolSize,
            long keepAliveTime,
            TimeUnit unit,
            BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handler
    ) {
        this.corePoolSize = corePoolSize;
        this.temporaryPoolSize = maximumPoolSize - corePoolSize;
        this.workQueue = workQueue;
        this.threadFactory = threadFactory;
        this.keepAliveTime = keepAliveTime;
        this.unit = unit;
    }

    //默认的构造方法
    public MyThreadPoolExecutor() {
        this.corePoolSize = 2;
        this.temporaryPoolSize = 2;
        this.workQueue = new LinkedBlockingQueue<>();
        this.threadFactory = Executors.defaultThreadFactory();
        this.keepAliveTime = 5;
        this.unit = TimeUnit.SECONDS;
    }

    //向线程池中提交任务
    @Override
    public void execute(Runnable command) {
        //1.当正式员工的数量小于员工上限时，则优先创建正式员工处理
        if (currentCoreSize < corePoolSize) {
            //优先创建正式员工
            //创建一个线程，这个线程中的任务就是不断的取任务-做任务，不考虑退出的问题
            CoreJob job = new CoreJob(workQueue, command);
            //线程工厂创建线程
            Thread thread = threadFactory.newThread(job);
            String name = String.format("正式员工-%d", currentCoreSize);
            thread.setName(name);
            thread.start();
            currentCoreSize++;
            return;
        }
        //走到这里，表示正式员工的数量==正式员工的上限
        //2.将任务放入优先级队列中，如果放入成功，execute执行结束，否则还需要继续
        //带阻塞的放入，需要立即看到结果
        boolean success = workQueue.offer(command);
        if (success == true) {
            //说明放入成功
            return;
        }
        //为实现方便，暂不考虑其他策略
        throw new RejectedExecutionException();
    }
}
